---
title: 从HDFS从读取JSON数据
---

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

使用PXF HDFS连接器读取JSON格式数据的数据。本节描述了如何使用PXF访问HDFS中的JSON数据，包括如何创建和查询引用HDFS中JSON文件的外部表。

## <a id="prereq"></a>先决条件

在尝试从HDFS读取或向HDFS写入数据之前，请确保已满足PXF Hadoop[先决条件](access_hdfs.html#hadoop_prereq)。

## <a id="hdfsjson_work"></a>使用JSON数据

JSON是基于文本的数据交换格式。JSON数据通常存储在带有 `.json`后缀的文件中。

`.json`文件将包含对象的集合。JSON对象是无序键/值对的集合。值可以是字符串(string)、数字(number)、true、false、null或对象(object)或数组(array)。您可以定义嵌套的JSON对象和数组。

样本JSON数据文件内容：

``` json
  {
    "created_at":"MonSep3004:04:53+00002013",
    "id_str":"384529256681725952",
    "user": {
      "id":31424214,
      "location":"COLUMBUS"
    },
    "coordinates":{
      "type":"Point",
      "values":[
         13,
         99
      ]
    }
  }
```

在上述的示例中，`user`是一个由名为`id`和`location`的字段组成的对象。要将`user`对象中的嵌套字段指定为Greenplum数据库外部表列，请使用`.`映射：

``` pre
user.id
user.location
```

`coordinates`是一个由名为`type`字段和名为`values`的整数数组组成的对象。使用`[]`来指定特定`values`数组中特定的元素作为Greenplum数据库外部表的列：

``` pre
coordinates.values[0]
coordinates.values[1]
```

有关JSON语法的详细信息，请参阅[JSON 简介](http://www.json.org/)。

### <a id="datatypemap_json"></a>JSON到Greenplum数据库数据类型映射</a>

要在Greenplum数据库中表示JSON数据，请将使用基本数据类型的值映射到相同类型的Greenplum数据库列。JSON支持复杂的数据类型包括投影和数组。 使用N级投影将嵌套对象和数组的成员映射到基本数据类型。

下表总结了JSON数据的外部映射规则。

<caption><span class="tablecap">表1. JSON映射</span></caption>

<a id="topic_table_jsondatamap"></a>

| JSON 数据类型                                                    | PXF/Greenplum Data Type                                                                                                                                                                                            |
|-------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 基本类型(integer, float, string, boolean, null) | 使用相应的Greenplum数据库内置数据类型；请参阅[Greenplum数据库数据类型](../ref_guide/data_types.html). |
| 数组(Array)                         | 使用`[]`括号标识基本数据类型数组特定成员的索引。|
| 对象(Object)                | 使用`.`点号指定基本类型的每一层投影(嵌套)。|

### <a id="topic_jsonreadmodes"></a>JSON数据读取模式

PXF支持两种数据读取模式。默认模式是每行一条完成的JSON记录。PXF还支持对跨多行的JSON记录进行操作的读取模式。

在接下来的示例中，您将使用两种模式对样本数据集进行操作。样本数据集的模式定义具有以下成员名称和数据类型的对象：

   - "created_at" - text
   - "id_str" - text
   - "user" - object
      - "id" - integer
      - "location" - text
   - "coordinates" - object (可选)
      - "type" - text
      - "values" - array
         - [0] - integer
         - [1] - integer


每行单条JSON记录数据如下：

``` pre
{"created_at":"FriJun0722:45:03+00002013","id_str":"343136551322136576","user":{
"id":395504494,"location":"NearCornwall"},"coordinates":{"type":"Point","values"
: [ 6, 50 ]}},
{"created_at":"FriJun0722:45:02+00002013","id_str":"343136547115253761","user":{
"id":26643566,"location":"Austin,Texas"}, "coordinates": null},
{"created_at":"FriJun0722:45:02+00002013","id_str":"343136547136233472","user":{
"id":287819058,"location":""}, "coordinates": null}
```  

这是用于多行JSON数据的数据集:

``` json
{
  "root":[
    {
      "record_obj":{
        "created_at":"MonSep3004:04:53+00002013",
        "id_str":"384529256681725952",
        "user":{
          "id":31424214,
          "location":"COLUMBUS"
        },
        "coordinates":null
      },
      "record_obj":{
        "created_at":"MonSep3004:04:54+00002013",
        "id_str":"384529260872228864",
        "user":{
          "id":67600981,
          "location":"KryberWorld"
        },
        "coordinates":{
          "type":"Point",
          "values":[
             8,
             52
          ]
        }
      }
    }
  ]
}
```

在下一节中您将为示例数据集创建JSON文件，并将其添加到HDFS中。

## <a id="jsontohdfs"></a>将样本JSON数据加载到HDFS

PXF HDFS连接器读取存储在HDFS本地的JSON文件。在使用Greenplum数据库查询JSON格式数据之前，该数据必须存在于HDFS中。

将上面的单行JSON记录样本数据集复制并黏贴到名为`singleline.json`的文件中。同样的，将多行JSON记录数据集复制并黏贴到名为`multiline.json`的文件中。

**注意**: 确保JSON文件中**没有**空白行。

将您刚创建的文件复制到HDFS中。如果您在上一个练习中没有创建`/data/pxf_examples`目录，请创建它。例如：

``` shell
$ hdfs dfs -mkdir /data/pxf_examples
$ hdfs dfs -put singleline.json /data/pxf_examples
$ hdfs dfs -put multiline.json /data/pxf_examples
```

数据加载到HDFS后，您可以使用Greenplum数据库和PXF查询和分析JSON数据。


## <a id="json_cet"></a>创建外部表

使用`hdfs:json`配置文件从HDFS中读取JSON格式的文件。以下语法创建一个引用此类文件的Greenplum数据库可读外部表：

``` sql
CREATE EXTERNAL TABLE <table_name>
    ( <column_name> <data_type> [, ...] | LIKE <other_table> )
LOCATION ('pxf://<path-to-hdfs-file>?PROFILE=hdfs:json[&<custom-option>=<value>[...]]')
FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import');
```

[CREATE EXTERNAL TABLE](../ref_guide/sql_commands/CREATE_EXTERNAL_TABLE.html)命令中使用的特定关键字和值见下表中描述。

| 关键字| 值|
|-------|-------------------------------------|
| \<path&#8209;to&#8209;hdfs&#8209;file\>    | HDFS数据存储中目录或文件的绝对路径 |
| PROFILE    | `PROFILE`关键字必须指定为`hdfs:json` |
| \<custom&#8209;option\>  | \<custom-option\>描述见下方|
| FORMAT 'CUSTOM' | 在 `hdfs:json`配置文件中使用 `FORMAT` `'CUSTOM'` 。 `CUSTOM` `FORMAT` 要求您指定为 `(FORMATTER='pxfwritable_import')`。 |

<a id="customopts"></a>
PXF支持单行和多行JSON记录。当您想读取多行JSON记录时，必须提供`IDENTIFIER` \<custom-option\> 和值。 使用这个\<custom-option\>标识JSON记录对象中第一个字段的成员名称：

| 选项关键字  | &nbsp;&nbsp;语法、&nbsp;&nbsp;示例&nbsp;&nbsp; | 描述 |
|-------|--------------|-----------------------|
| IDENTIFIER  | `&IDENTIFIER=<value>`<br>`&IDENTIFIER=created_at`| 仅在访问多行JSON记录时，才必须在`LOCATION`字符串中指定`IDENTIFIER`关键字和值。 使用这个值标识JSON记录对象中第一个字段的成员名称。 |


## <a id="jsonexample1"></a>示例：读取单行记录的JSON文件

使用以下[CREATE EXTERNAL TABLE](../ref_guide/sql_commands/CREATE_EXTERNAL_TABLE.html) SQL命令创建一个引用每条记录单行的JSON数据文件的可读外部表。

``` sql 
CREATE EXTERNAL TABLE singleline_json_tbl(
  created_at TEXT,
  id_str TEXT,
  "user.id" INTEGER,
  "user.location" TEXT,
  "coordinates.values[0]" INTEGER,
  "coordinates.values[1]" INTEGER
)
LOCATION('pxf://data/pxf_examples/singleline.json?PROFILE=hdfs:json')
FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import');
```

注意使用`.`投影访问`user`和`coordinates`对象中的嵌套字段。还要注意使用`[]`来访问`coordinates.values[]`数组中的特定元素。

查询外部表中的JSON数据:

``` sql
SELECT * FROM singleline_json_tbl;
```

## <a id="jsonexample2" class="no-quick-link"></a>示例：读取多行记录的JSON文件

从多行JSON记录文件中创建可读外部表的SQL命令和上面单行JSON记录的非常类似。当您要读取多行JSON记录时，您必须额外指定`LOCATION`子句的`IDENTIFIER`关键字和值。例如：

``` sql
CREATE EXTERNAL TABLE multiline_json_tbl(
  created_at TEXT,
  id_str TEXT,
  "user.id" INTEGER,
  "user.location" TEXT,
  "coordinates.values[0]" INTEGER,
  "coordinates.values[1]" INTEGER
)
LOCATION('pxf://data/pxf_examples/multiline.json?PROFILE=hdfs:json&IDENTIFIER=created_at')
FORMAT 'CUSTOM' (FORMATTER='pxfwritable_import');
```

`created_at`标识示例数据模式中JSON记录`record_obj`中第一个字段的成员名称。

查询外部表中的JSON数据：

``` sql
SELECT * FROM multiline_json_tbl;
```

